#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtGui/qaction.h>
#include <iostream>
#include <fstream>
#include <cstdio>

using namespace std;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindowClass)
{
    ui->setupUi(this);
    timer = new QTimer(this);
    time = new QTime();
    grabar = false;
    posMuestra = 0;
    ui->qwtPlot->setAutoReplot(true);

    //Establece valor minimo y maximo de eje Y
    ui->qwtPlot->setAxisScale(0, this->ui->spinMin->value(), this->ui->spinMax->value());
    for(int i=0; i < 2000; i++)
    {
        x[i] = i;
    }

    //MENU FUENTE DE DATOS
    QActionGroup *group = new QActionGroup(ui->mainToolBar);
    memoria = new QAction("Desde Memoria", group);
    memoria->setCheckable(true);
    archivo = new QAction("Desde Archivo", group);
    archivo->setCheckable(true);
    puerto = new QAction("Desde Puerto", group);
    puerto->setCheckable(true);
    ui->mainToolBar->addAction(memoria);
    ui->mainToolBar->addAction(archivo);
    ui->mainToolBar->addAction(puerto);
    memoria->setChecked(true);
    ui->mainToolBar->addSeparator();
    QAction *cerrardata = ui->mainToolBar->addAction("Cerrar data");
    ui->mainToolBar->addSeparator();
    QActionGroup *group2 = new QActionGroup(ui->mainToolBar);
    QAction *grabarData = new QAction("Grabar Muestra", group2);
    grabarData->setCheckable(true);
    parar = new QAction("Parar", group2);
    parar->setCheckable(true);
    ui->mainToolBar->addAction(grabarData);
    ui->mainToolBar->addAction(parar);

    ui->statusBar->showMessage("Seleccione el Algoritmos deseado y "
                               "presione Plotear para ver los cambios");

    connect(memoria, SIGNAL(triggered()), this, SLOT(refresh()));
    connect(archivo, SIGNAL(triggered()), this, SLOT(refresh()));
    connect(puerto, SIGNAL(triggered()), this, SLOT(refresh()));
    connect(cerrardata, SIGNAL(triggered()), this, SLOT(cerrarDataSource()));
    connect(grabarData, SIGNAL(triggered()), this, SLOT(grabarDatos()));
    connect(parar, SIGNAL(triggered()), this, SLOT(pararGrabacion()));
    connect(ui->actionCalibrar, SIGNAL(triggered()), this, SLOT(refresh()));
    connect(ui->actionFiltro, SIGNAL(triggered()), this, SLOT(refresh()));
    connect(ui->actionIntegrar, SIGNAL(triggered()), this, SLOT(refresh()));
    connect(ui->checkIntegrar, SIGNAL(clicked()), this, SLOT(refresh()));
    connect(ui->checkCalibrar, SIGNAL(clicked()), this, SLOT(refresh()));
    connect(ui->checkFiltrar, SIGNAL(clicked()), this, SLOT(refresh()));

    this->plotear();
}

void MainWindow::cerrarDataSource()
{
    buffer.stopThread();
    timer->stop();
    this->puerto->setChecked(false);
    this->limpiar();
    ui->qwtPlot->replot();
}

void MainWindow::grabarDatos()
{
    grabar = true;
    time->start();
}

void MainWindow::pararGrabacion()
{
    grabar = false;
    this->grabarArchivo(posMuestra);
}

void MainWindow::refresh()
{
    if(timer->isActive())
    {
        timer->stop();
    }
    this->limpiar();
    this->plotear();
}

void MainWindow::limpiar()
{
    ui->qwtPlot->clear();
}

void MainWindow::plotear()
{
    bool integrar = ui->actionIntegrar->isChecked() || ui->checkIntegrar->isChecked();
    bool calibrar = ui->actionCalibrar->isChecked() || ui->checkCalibrar->isChecked();
    bool filtrar = ui->actionFiltro->isChecked() || ui->checkFiltrar->isChecked();
    DataSource data(integrar, calibrar, filtrar);

    this->data = data;

    //seleccionar segun fuente de datos elegida
    if(this->puerto->isChecked())
    {
        buffer.initialize();
        buffer.start();
        connect(timer, SIGNAL(timeout()), this, SLOT(cargarDatosContinuos()));
        timer->start(this->ui->spinTiempo->value());
    }
    else
    {
        double* val;
        if(this->archivo->isChecked())
        {
            val = this->data.obtenerMuestra(data.ARCHIVO);
        }
        else
        {
            val = this->data.obtenerMuestra(data.MEMORIA);
        }

        this->cargarDatos(val, this->data.getSize());
    }
}

void MainWindow::cargarDatosContinuos()
{
    int size = ui->spinEscala->value();

    double* y = buffer.getValoresX(size);
    double* y2 = buffer.getValoresY(size);
    double* y3 = buffer.getValoresZ(size);

    if(grabar)
    {
        for(int i=100; i < size; i++)
        {
            if(posMuestra == 200000)
            {
                posMuestra = 0;
                grabar = false;
                this->grabarArchivo(200000);
                this->parar->setChecked(true);
                break;
            }
            if(y[i] == 0)
            {
                i--;
                muestra[posMuestra] = y[i];
                posMuestra++;
                break;
            }
        }
    }

    ui->qwtPlot->clear();

    if(ui->checkX->isChecked())
    {
        curve1 = new QwtPlotCurve();
        curve1->setData(x, y, size);
        curve1->attach(ui->qwtPlot);
    }
    if(ui->checkY->isChecked())
    {
        curve2 = new QwtPlotCurve();
        curve2->setData(x, y2, size);
        curve2->setPen(QPen(Qt::blue));
        curve2->attach(ui->qwtPlot);
    }
    if(ui->checkZ->isChecked())
    {
        curve3 = new QwtPlotCurve();
        curve3->setData(x, y3, size);
        curve3->setPen(QPen(Qt::red));
        curve3->attach(ui->qwtPlot);
    }

    this->mostrarPosicion();
}

void MainWindow::cargarDatos(double *val, int size)
{
    double x[size];
    double y[size];

    for(int i=0; i<size; i++)
    {
        y[i] = val[i];
    }

    for(int i=0; i<size; i++)
    {
        x[i] = i;
    }

    curve1 = new QwtPlotCurve();
    curve1->setData(x, y, size);
    size += size;

    curve1->attach(ui->qwtPlot);

    this->mostrarPosicion();
}

void MainWindow::mostrarPosicion()
{
    if(ui->actionIntegrar->isChecked() || ui->checkIntegrar->isChecked())
    {
        double desp = this->data.obtenerPosicion();
        char mensaje[50];
        sprintf (mensaje, "Desplazamiento Realizado = %.4f", desp);
        ui->statusBar->showMessage(mensaje);
        ui->linePosicion->setText(mensaje);
    }
}

void MainWindow::grabarArchivo(int size)
{
    fstream file_op("/home/gato/syriox.txt",ios::out);

    //Primera linea: cantidad de milisegundos durante los que
    //se grabo la muestra
    file_op << time->elapsed();
    //file_op << "function [y] = get_acel_values()" << endl;
    //file_op << "y = [..." << endl;

    for( int i = 0; i < size; i++)
    {
        if( i % 8 == 0)
            file_op << "..." << endl;
        file_op << muestra[i];
        file_op << "\t";
    }
    //file_op << "];";
    file_op.close();

    //cout << "ARCHIVO GUARDADO" << endl;
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_spinEscala_valueChanged(int position)
{
    this->ui->horizontalSlider->setValue(position);
}

void MainWindow::on_spinMax_valueChanged(int value)
{
    ui->qwtPlot->setAxisScale(0, this->ui->spinMin->value(), value);
}

void MainWindow::on_spinMin_valueChanged(int value)
{
    ui->qwtPlot->setAxisScale(0, value, this->ui->spinMax->value());
}

void MainWindow::on_horizontalSlider_sliderMoved(int position)
{
    this->ui->spinEscala->setValue(position);
}

void MainWindow::on_pushButton_clicked()
{
    if(ui->checkX->isChecked() || ui->checkY->isChecked() || ui->checkZ->isChecked())
    {
        ui->checkX->setChecked(false);
        ui->checkY->setChecked(false);
        ui->checkZ->setChecked(false);
        ui->pushButton->setText("Refresh Grafico");
    }
    else
    {
        ui->checkX->setChecked(true);
        ui->pushButton->setText("Parar Grafico");
    }
}
